﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

/// <summary>
/// 引导用户完成找回密码的验证
/// 在登录界面点击“忘记密码？”链接调用本页面
/// 不验证用户有没有登录
/// 分为三个阶段：
/// 1. 输入用户名和邮箱地址，将邮箱地址暂时存入cookie方便后面使用
/// 2. 输入安全问题的答案
/// </summary>
public partial class findPassword : System.Web.UI.Page
{
    /// <summary>
    /// 第一次访问（不是回发）时仅显示第一部分
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            step_2.Visible = false;
            step_3.Visible = false;
        }
    }

    /// <summary>
    /// 步骤一的按钮
    /// 检查数据有效性
    /// 验证用户名是否存在、安全邮箱是否正确、用户是否启用了密码保护功能
    /// 如果正确将邮箱地址存入cookie方便后面使用（temp_userid,temp_username,temp_emailaddress)
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void submit_step_1_Click(object sender, EventArgs e)
    {
        //检查输入数据的合法性，主要是邮箱地址
        Regex emailAddressChecker = new Regex(@"^(?("")(""[^""]+?""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9]{2,17}))$", RegexOptions.IgnoreCase);
        if (userName_text.Text.Trim() == string.Empty)
        {
            notification_step_1.InnerHtml = "请输入用户名 FROM SERVER";
            return;
        }
        else if (emailAddress_text.Text.Trim() == string.Empty)
        {
            notification_step_1.InnerHtml = "请输入邮箱地址 FROM SERVER";
            return;
        }
        else if (!emailAddressChecker.IsMatch(emailAddress_text.Text.Trim()))
        {
            notification_step_1.InnerHtml = "您输入的邮箱地址不合法 FROM SERVER";
            return;
        }
        else
        {
            string userName = userName_text.Text.Trim();
            string emailAddress = emailAddress_text.Text.Trim();

            //合法性检查完毕，执行一致性检查
            ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["connectionString"];
            using (SqlConnection dataBaseConnection = new SqlConnection(settings.ConnectionString))
            {
                dataBaseConnection.Open();

                //验证用户名是否存在
                string queryString = "SELECT userID, email " +
                                     "FROM users " +
                                     "WHERE username = @username";
                SqlCommand command = new SqlCommand(queryString, dataBaseConnection);
                SqlParameter usernameParameter = new SqlParameter("@username", userName);
                command.Parameters.Add(usernameParameter);
                SqlDataReader reader;
                try
                {
                    reader = command.ExecuteReader();
                }
                catch (Exception exception)
                {
                    notification_step_1.InnerHtml = "数据库方面发生了错误，请联系我们以解决 AFTER GET email " + exception.Message;
                    return;
                }

                if (!reader.HasRows)
                {
                    notification_step_1.InnerHtml = "您输入的用户名不存在，请核对后重新输入";
                    return;
                }
                else
                {
                    reader.Read();
                    string emailAddress_fromDB = reader["email"].ToString();
                    string userID = reader["userID"].ToString();
                    reader.Close();

                    //检查用户是否已经启用了密码保护
                    queryString = "SELECT Verified " +
                                  "FROM PasswordProtection " +
                                  "WHERE userID = @userID";
                    command.CommandText = queryString;
                    command.Parameters.Clear();
                    SqlParameter userIDParameter = new SqlParameter("@userID", userID);
                    command.Parameters.Add(userIDParameter);
                    try
                    {
                        reader = command.ExecuteReader();
                    }
                    catch (Exception exception)
                    {
                        notification_step_1.InnerHtml = "数据库方面发生了错误，请联系我们以解决 AFTER CHECK PASSWORD PROTECTION STATUS " + exception.Message;
                        return;
                    }

                    if (!reader.HasRows)
                    {
                        step_1.InnerHtml = "很遗憾我们不能为您提供找回密码服务，因为您的账号没有启用密码保护功能";
                        return;
                    }

                    reader.Read();
                    if (reader["Verified"].ToString() == "0")
                    {
                        step_1.InnerHtml = "很遗憾我们不能为您提供找回密码服务，因为您的账号没有启用密码保护功能（没有验证邮箱）";
                        return;
                    }
                    reader.Close();

                    //如果执行到此，证明用户已经启用了密码保护，验证邮箱地址是否一致
                    if (emailAddress != emailAddress_fromDB)
                    {
                        notification_step_1.InnerHtml = "您输入的邮箱地址不正确";
                        return;
                    }
                    else
                    {
                        //所有检查通过，降临时数据存入cookie，方便后面使用
                        Response.Cookies.Set(new HttpCookie("temp_emailaddress", emailAddress));
                        Response.Cookies.Set(new HttpCookie("temp_userid", userID));
                        Response.Cookies.Set(new HttpCookie("temp_username", userName));

                        //显示步骤二的内容
                        step_1.Visible = false;
                        step_2.Visible = true;
                        step_3.Visible = false;

                        //从数据库中读取问题
                        queryString = "SELECT Question1, Question2 " +
                                      "FROM PasswordProtection " +
                                      "WHERE userID = @userID";
                        command.CommandText = queryString;
                        command.Parameters.Clear();
                        command.Parameters.Add(userIDParameter);
                        try
                        {
                            reader = command.ExecuteReader();
                        }
                        catch (Exception exception)
                        {
                            notification_step_1.InnerHtml = "数据库方面发生了错误，请联系我们以解决 AFTER GET QUESTIONS " + exception.Message;
                            return;
                        }

                        reader.Read();
                        string question1 = reader["Question1"].ToString();
                        string question2 = reader["Question2"].ToString();
                        reader.Close();

                        //将问题显示在页面上，并且只读
                        question1_text.Text = question1;
                        question1_text.ReadOnly = true;
                        question2_text.Text = question2;
                        question2_text.ReadOnly = true;
                    }
                }
            }
        }
    }
    /// <summary>
    /// 步骤二的按钮
    /// 检查数据有效性
    /// 比较答案是否正确
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void submit_step_2_Click(object sender, EventArgs e)
    {
        //检查两个答案是否填写完整
        if (answer1_text.Text.Trim() == string.Empty)
        {
            notification_step_2.InnerHtml = "请填写问题 1 的答案 FROM SERVER";
            return;
        }
        else if (answer2_text.Text.Trim() == string.Empty)
        {
            notification_step_2.InnerHtml = "请填写问题 2 的答案 FROM SERVER";
            return;
        }
        else
        {
            byte[] answer1 = SHA1.Create().ComputeHash(Encoding.Unicode.GetBytes(answer1_text.Text.Trim()));
            byte[] answer2 = SHA1.Create().ComputeHash(Encoding.Unicode.GetBytes(answer2_text.Text.Trim()));

            //从数据库中读取密保问题的答案
            ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["connectionString"];
            using (SqlConnection dataBaseConnection = new SqlConnection(settings.ConnectionString))
            {
                dataBaseConnection.Open();

                string queryString = "SELECT Answer1, Answer2 " +
                                     "FROM PasswordProtection " +
                                     "WHERE userID = @userID";
                SqlCommand command = new SqlCommand(queryString, dataBaseConnection);
                SqlParameter userIDParameter = new SqlParameter("@userID", Request.Cookies["temp_userid"].Value);
                command.Parameters.Add(userIDParameter);
                SqlDataReader reader;
                try
                {
                    reader = command.ExecuteReader();
                }
                catch (Exception exception)
                {
                    notification_step_2.InnerHtml = "数据库方面发生了错误，请联系我们以解决 AFTER GET ANSWERS " + exception.Message;
                    return;
                }

                reader.Read();

                //比较密保问题答案是否一致
                if (!Tools.byteArrayEquals(answer1, (byte[])reader["Answer1"]))
                {
                    notification_step_2.InnerHtml = "问题 1 的答案错误";
                    return;
                }
                else if (!Tools.byteArrayEquals(answer2, (byte[])reader["Answer2"]))
                {
                    notification_step_2.InnerHtml = "问题 2 的答案错误";
                    return;
                }
                else
                {
                    //答案一致，发送邮件
                    try
                    {
                        Tools.SendFindPasswordEmail(Request.Cookies["temp_emailaddress"].Value, Request.Cookies["temp_userid"].Value, Request.Cookies["temp_username"].Value);
                    }
                    catch (Exception exception)
                    {
                        notification_step_2.InnerHtml = "发送邮件时出现了错误 " + exception.Message;
                        return;
                    }

                    //删除临时cookie
                    Response.Cookies["temp_emailaddress"].Expires = DateTime.Now.AddDays(-1);
                    Response.Cookies["temp_userid"].Expires = DateTime.Now.AddDays(-1);
                    Response.Cookies["temp_username"].Expires = DateTime.Now.AddDays(-1);

                    //进入step_3
                    step_1.Visible = false;
                    step_2.Visible = false;
                    step_3.Visible = true;
                }
            }
        }
    }
}